package com.moss.cloud.base.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moss.cloud.base.api.model.from.*;
import com.moss.cloud.base.api.model.param.UserListParam;
import com.moss.cloud.base.api.model.param.UserPageParam;
import com.moss.cloud.base.api.model.vo.BaseUserVO;
import com.moss.cloud.base.api.model.vo.UserPageVO;
import com.moss.cloud.base.biz.event.*;
import com.moss.cloud.base.biz.mapper.SysUserMapper;
import com.moss.cloud.base.biz.model.AccountLockRecord;
import com.moss.cloud.base.biz.model.TenantConfig;
import com.moss.cloud.base.biz.service.*;
import com.moss.cloud.base.biz.utils.DataProUtil;
import com.moss.cloud.common.base.model.po.*;
import com.moss.cloud.common.base.utils.PageUtil;
import com.moss.cloud.common.core.enums.TenantConfigEnum;
import com.moss.cloud.common.core.enums.state.Deleted;
import com.moss.cloud.common.core.enums.state.LockAcct;
import com.moss.cloud.common.core.exception.SystemErrorType;
import com.moss.cloud.common.core.model.dto.UserEventDTO;
import com.moss.cloud.common.core.model.vo.UserInfo;
import com.moss.cloud.common.core.utils.*;
import com.moss.cloud.common.core.constant.Constant;
import com.moss.cloud.common.security.annotation.RequiresDept;
import com.moss.cloud.common.security.annotation.RequiresTenant;
import com.moss.cloud.common.security.component.RedisTemplateOps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户信息表服务实现
 *
 * @author 瑾年
 * @date 2023年3月23日
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    /**
     * 用户密码加密
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Resource
    RedisTemplateOps redisTemplateOps;

    @Resource
    ISystemConfigService systemConfigService;

    @Resource
    ITenantConfigService tenantConfigService;

    @Resource
    ISysUserRoleService sysUserRoleService;

    @Resource
    IAccountLockRecordService accountLockRecordService;

    @Resource
    ISysDeptService sysDeptService;
    @Resource
    ISysMenuService sysMenuService;

    /**
     * 保存用户信息--通用用户注册
     *
     * @param sysUserForm
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUser(SysUserForm sysUserForm) throws Exception {
        // 业务数据校验
        SysUserForm.checkFrom(sysUserForm);
        // 重复性检验
        this.checkNotRepeat(sysUserForm);
        // 客户端传了密码，AES解密之后用BCryptPassword加密保存
        if (StringUtils.isNotBlank(sysUserForm.getPassword())) {
            String newPwd = AESUtil.aesDecrypt(sysUserForm.getPassword(), Constant.KEY);
            sysUserForm.setPassword(passwordEncoder().encode(newPwd));
        }
        // 客户端没有传密码查询租户密码配置加密保存
        String newPwd;
        if (StringUtils.isBlank(sysUserForm.getPassword()) && Objects.nonNull(sysUserForm.getTenantId())) {
            TenantConfig tenantConfig = tenantConfigService.getTenantConfig(sysUserForm.getTenantId(), TenantConfigEnum.DEFAULT_PASSWORD.code());
            if (Objects.nonNull(tenantConfig)) {
                newPwd = AESUtil.aesDecrypt(tenantConfig.getConfigValue(), Constant.KEY);
            } else {
                SystemConfig systemConfig = systemConfigService.getSystemConfig(Constant.DEFAULT_PASSWORD);
                newPwd = AESUtil.aesDecrypt(systemConfig.getConfigValue(), Constant.KEY);
            }
            sysUserForm.setPassword(passwordEncoder().encode(newPwd));
        }
        // 租户ID是空的使用系统默认密码
        if (StringUtils.isBlank(sysUserForm.getPassword()) && Objects.isNull(sysUserForm.getTenantId())) {
            SystemConfig systemConfig = systemConfigService.getSystemConfig(Constant.DEFAULT_PASSWORD);
            newPwd = AESUtil.aesDecrypt(systemConfig.getConfigValue(), Constant.KEY);
            sysUserForm.setPassword(passwordEncoder().encode(newPwd));
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserForm, sysUser);
        BooleanHandel.isTrue(StringUtils.isBlank(sysUserForm.getAvatar())).trueHandle(() -> {
            SystemConfig systemConfig = systemConfigService.getSystemConfig(Constant.DEFAULT_USER_PHOTO);
            sysUser.setAvatar(systemConfig.getConfigValue());
        });
        Boolean saveFlag = this.save(sysUser);
        // 发布一个用户创建事件
        SpringContextHolder.publishEvent(new UserCreateEvent(this, sysUser));
        return saveFlag.equals(Boolean.TRUE) ? this.saveUserRole(sysUser.getId(), sysUserForm) : Boolean.FALSE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeUser(PreUserFrom preUserFrom) {
        // 删除用户信息
        SysUser user = this.findByUserId(preUserFrom.getUserId());
        BooleanHandel.trueThrow(Objects.isNull(user)).throwMessage(SystemErrorType.DATE_EMPTY);
        Boolean updateFlag = this.update(new UpdateWrapper<SysUser>().lambda()
                .eq(SysUser::getId, preUserFrom.getUserId())
                .set(SysUser::getDeleted, Deleted.DELETE.code())
                .set(SysUser::getAccountNonLocked, Boolean.FALSE)
        );
        // 删除用户对应的权限信息
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda()
                .eq(SysUserRole::getUserId, preUserFrom.getUserId()));
        if (CollectionUtils.isNotEmpty(sysUserRoles)) {
            sysUserRoles.forEach(role -> role.setDeleted(Deleted.DELETE.code()));
        }
        // 发布用户更新事件
        SpringContextHolder.publishEvent(new UserRemoveEvent(this, user));
        return Objects.equals(updateFlag, Boolean.TRUE) ? sysUserRoleService.saveOrUpdateBatch(sysUserRoles) : Boolean.FALSE;
    }

    /**
     * 构建保存用户角色
     *
     * @param userId
     * @param sysUserForm
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUserRole(Long userId, SysUserForm sysUserForm) {
        UserRoleFrom userRoleFrom = new UserRoleFrom();
        userRoleFrom.setUserId(userId);
        userRoleFrom.setRoleIds(CollectionUtils.isNotEmpty(sysUserForm.getRoleIds()) ?
                sysUserForm.getRoleIds() : Collections.emptyList());
        return sysUserRoleService.saveBatchUserRole(userRoleFrom);
    }

    /**
     * 校验手机号，邮箱，openid不重复
     *
     * @param sysUserForm
     */
    public void checkNotRepeat(SysUserForm sysUserForm) {
        BooleanHandel.isTrue(StringUtils.isNotBlank(sysUserForm.getUsername())).trueHandle(() -> {
            log.info("用户名不为空校验数据:{}", sysUserForm.getUsername());
            SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().lambda()
                    .eq(SysUser::getUsername, sysUserForm.getUsername()));
            BooleanHandel.trueThrow(Objects.nonNull(sysUser)).throwMessage(SystemErrorType.USER_NAME_REPEAT);
        });
        BooleanHandel.isTrue(StringUtils.isNotBlank(sysUserForm.getMobile())).trueHandle(() -> {
            log.info("手机号不为空校验数据:{}", sysUserForm.getMobile());
            SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().lambda()
                    .eq(SysUser::getMobile, sysUserForm.getMobile())
                    .notIn(SysUser::getDeleted, Deleted.DELETE.code()));
            BooleanHandel.trueThrow(Objects.nonNull(sysUser)).throwMessage(SystemErrorType.MOBILE_REPEAT);
        });
        BooleanHandel.isTrue(StringUtils.isNotBlank(sysUserForm.getEmail())).trueHandle(() -> {
            log.info("邮箱不为空校验数据:{}", sysUserForm.getEmail());
            SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().lambda()
                    .eq(SysUser::getEmail, sysUserForm.getEmail())
                    .notIn(SysUser::getDeleted, Deleted.DELETE.code()));
            BooleanHandel.trueThrow(Objects.nonNull(sysUser)).throwMessage(SystemErrorType.EMAIL_REPEAT);
        });
        BooleanHandel.isTrue(StringUtils.isNotBlank(sysUserForm.getOpenId())).trueHandle(() -> {
            log.info("OPENID不为空校验数据:{}", sysUserForm.getOpenId());
            SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().lambda()
                    .eq(SysUser::getEmail, sysUserForm.getOpenId())
                    .notIn(SysUser::getDeleted, Deleted.DELETE.code()));
            BooleanHandel.trueThrow(Objects.nonNull(sysUser)).throwMessage(SystemErrorType.OPENID_REPEAT);
        });
    }

    /**
     * 手动锁定账号
     *
     * @param userLockFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean lockAccount(UserLockFrom userLockFrom) {
        // -------------------------------以下业务处理不需要开发人员实现，注意理解整个锁定的逻辑和处理方案-----------------------
        // 账号锁定之后是不能登录的，这个已经实现，所以需要在到了解锁时间去解锁账号
        // 4种处理方案
        // （1）、http调用创建定时任务接口按照解锁时间去执行任务--根据基础能力设计原理，此方案不采取
        // （2）、扫描账号锁定记录表去解锁--根据基础能力设计原理，扫描表的不采取
        // （3）、发布一个MQ消息，这消息设置为定期发布，MQ收到这个消息后不会直接推送给消费者，在时间到了之后自动发布-rocketMQ实现这个比较困难，
        // 他的定时发布消息不支持自定义时间，可以用解锁时间计算最大延迟消息间隔
        // （rocketMQ支持延迟间隔messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h）
        // 设置为MQ支持的类型，当接收到消息后计算是否到解锁时间，未到解锁时间重新发布一个延迟消息时间为剩余时间最大间隔，类推--推荐
        // （4）、将被锁定的账号记录在redis中，过期时间设置为解锁时间，监听redis过期KEY，去解锁--
        // 需要注意redis集群的时候过期key监听有一定的BUG，需要手动解决--推荐
        // 查询用户是否存在
        SysUser user = this.findByUserId(userLockFrom.getUserId());
        BooleanHandel.trueThrow(Objects.isNull(user)).throwMessage(SystemErrorType.DATE_EMPTY);
        log.info("锁定状态:{}", user.getAccountNonLocked());
        BooleanHandel.trueThrow(Boolean.FALSE.equals(user.getAccountNonLocked())).throwMessage(SystemErrorType.ALREADY_LOCK);
        LocalDateTime lockTime = LocalDateTime.now();
        accountLockRecordService.saveOrUpdateLockAccount(lockTime, userLockFrom);
        Boolean lockFlag = this.updateLockState(userLockFrom.getUserId(), LockAcct.LOCK.code());
        // 发布一个用户账号锁定事件，业务服务可用来处理特殊业务，如通知用户账号被锁定
        UserEventDTO dto = this.buildUserEventDTO(LockAcct.LOCK.code(), userLockFrom.getUnlockTime(), lockTime,
                userLockFrom.getLockReason(), "", user.getId());
        SpringContextHolder.publishEvent(new UserLockEvent(this, dto));
        return lockFlag;
    }

    /**
     * 手动解锁账号
     *
     * @param userUnlockFrom
     * @return
     */
    public Boolean unlockAccount(UserUnlockFrom userUnlockFrom) {
        SysUser user = this.findByUserId(userUnlockFrom.getUserId());
        BooleanHandel.trueThrow(Objects.isNull(user)).throwMessage(SystemErrorType.DATE_EMPTY);
        log.info("锁定状态:{}", user.getAccountNonLocked());
        BooleanHandel.trueThrow(Boolean.TRUE.equals(user.getAccountNonLocked())).throwMessage(SystemErrorType.NOT_LOCKED);
        LocalDateTime time = LocalDateTime.now();
        AccountLockRecord accountLockRecord = accountLockRecordService.findByUserId(userUnlockFrom.getUserId());
        accountLockRecordService.unlockAccount(time, userUnlockFrom);
        Boolean unlockFlag = this.updateLockState(userUnlockFrom.getUserId(), LockAcct.UNLOCK.code());
        // 发布一个用户账号解锁事件，业务服务可用来处理特殊业务，如通知用户账号解锁
        UserEventDTO dto = this.buildUserEventDTO(LockAcct.UNLOCK.code(), time, accountLockRecord.getLockTime(),
                accountLockRecord.getLockReason(), userUnlockFrom.getUnlockReason(), user.getId());
        SpringContextHolder.publishEvent(new UserLockEvent(this, dto));
        return unlockFlag;
    }

    /**
     * 构建锁定信息
     *
     * @param lockStatus
     * @param unlockTime
     * @param lockTime
     * @param lockReason
     * @param unlockReason
     * @return
     */
    private UserEventDTO buildUserEventDTO(Boolean lockStatus, LocalDateTime unlockTime,
                                           LocalDateTime lockTime,
                                           String lockReason, String unlockReason, Long userId) {
        UserEventDTO userEventDTO = new UserEventDTO();
        userEventDTO.setLockReason(lockReason);
        userEventDTO.setUnlockTime(unlockTime);
        userEventDTO.setLockTime(lockTime);
        userEventDTO.setUnlockReason(unlockReason);
        userEventDTO.setLockState(lockStatus);
        userEventDTO.setUserId(userId);
        return userEventDTO;
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public SysUser findByUserId(Long userId) {
        return this.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getId, userId));
    }

    /**
     * 修改用户账号锁定状态
     *
     * @param userId
     * @param lockState
     * @return
     */
    public Boolean updateLockState(Long userId, Boolean lockState) {
        return this.update(new UpdateWrapper<SysUser>().lambda()
                .eq(SysUser::getId, userId)
                .set(SysUser::getAccountNonLocked, lockState));
    }

    /**
     * 分页查询用户信息
     *
     * @param userPageParam
     * @return
     */
    @Override
    @RequiresDept
    @RequiresTenant
    public IPage<UserPageVO> userPage(UserPageParam userPageParam) {
        IPage<UserPageVO> userPageVOIPage = new Page<>();
        Page<SysUser> page = PageUtil.createPage(userPageParam.getCurrent(), userPageParam.getSize());
        QueryWrapper<SysUser> queryWrapper = this.createWrapper(userPageParam);
        IPage<SysUser> userPage = this.page(page, queryWrapper);
        BeanUtils.copyProperties(userPage, userPageVOIPage);
        List<UserPageVO> userPages = CollectionUtils.isNotEmpty(userPage.getRecords()) ?
                userPage.getRecords().stream().map(item -> {
                    UserPageVO userPageVO = new UserPageVO();
                    BeanUtils.copyProperties(item, userPageVO);
                    return userPageVO;
                }).collect(Collectors.toList()) : Collections.emptyList();
        userPageVOIPage.setRecords(userPages);
        return userPageVOIPage;
    }

    /**
     * 创建查询参数
     *
     * @param userPageParam
     * @return
     */
    public QueryWrapper<SysUser> createWrapper(UserPageParam userPageParam) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().notIn(SysUser::getDeleted, Deleted.DELETE.code());
        queryWrapper.lambda().eq(StringUtils.isNotBlank(userPageParam.getUsername()), SysUser::getUsername, userPageParam.getUsername());
        queryWrapper.lambda().like(StringUtils.isNotBlank(userPageParam.getName()), SysUser::getName, userPageParam.getName());
        queryWrapper.lambda().like(StringUtils.isNotBlank(userPageParam.getMobile()), SysUser::getMobile, userPageParam.getMobile());
        queryWrapper.lambda().like(StringUtils.isNotBlank(userPageParam.getEmail()), SysUser::getEmail, userPageParam.getEmail());
        queryWrapper.lambda().eq(userPageParam.getAccountNonLocked() != null, SysUser::getAccountNonLocked, userPageParam.getAccountNonLocked());
        queryWrapper.lambda().eq(userPageParam.getSex() != null, SysUser::getSex, userPageParam.getSex());
        queryWrapper.lambda().ge(userPageParam.getStartTime() != null, SysUser::getCreatedTime, userPageParam.getStartTime());
        queryWrapper.lambda().ge(userPageParam.getEndTime() != null, SysUser::getCreatedTime, userPageParam.getEndTime());
        Long tenantId = UserContextHolder.getTenantId();
        Long deptId = UserContextHolder.getDeptId();
        log.info("参数部门ID:{}，当前用户部门ID:{}", userPageParam.getDeptId(), deptId);
        // 超级租户查看所有用户数据
        BooleanHandel.isTureOrFalse(Constant.SUPER_TENANT.equals(tenantId) && Objects.isNull(userPageParam.getDeptId()) &&
                        !userPageParam.getShowTenant())
                .trueOrFalseHandle(() -> {
                    log.info("当前租户是超级租户，查询类型为所有,租户ID->:{}", tenantId);
                    log.info("超级租户查看所有用户数据,租户ID->:{}", tenantId);
                }, () -> {
                    log.info("其他的都按照租户ID查询,租户ID->:{}", tenantId);
                    queryWrapper.lambda().eq(SysUser::getTenantId, tenantId);
                    BooleanHandel.isTrue(userPageParam.getDeptId() != null).trueHandle(() -> {
                        log.info("参数部门ID不为空按照参数部门查询及其子部门的用户,-部门ID:{}", userPageParam.getDeptId());
                        // 获取参数部门及其子部门集合
                        List<SysDept> sysDepts = sysDeptService.sysDepts(userPageParam.getDeptId());
                        List<Long> deptIds = DataProUtil.deptIds(sysDepts);
                        // 校验当前参数部门ID是否属于当前用户的部门及其子部门
                        Boolean isUserSubDept = sysDeptService.isUserSubDept(deptId, userPageParam.getDeptId());
                        BooleanHandel.trueThrow(!isUserSubDept).throwMessage(SystemErrorType.NO_SUB_DEPT);
                        queryWrapper.lambda().in(SysUser::getDeptId, deptIds);
                    });
                    BooleanHandel.isTrue(userPageParam.getDeptId() == null && !Constant.NO_TENANT_AND_DEPT.equals(deptId)).trueHandle(() -> {
                        log.info("参数部门ID为空按照当前登录用户的部门ID查询当前部门及其子部门用户数据,-部门ID:{}", deptId);
                        // 获取用户部门及其子部门集合
                        List<SysDept> sysDepts = sysDeptService.sysDepts(deptId);
                        List<Long> deptIds = DataProUtil.deptIds(sysDepts);
                        queryWrapper.lambda().in(SysUser::getDeptId, deptIds);
                    });
                });
        return queryWrapper;
    }

    /**
     * 管理员添加用户
     *
     * @param sysUserForm
     * @return
     * @throws Exception
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public Boolean adminAddUser(SysUserForm sysUserForm) throws Exception {
        Long tenantId = UserContextHolder.getTenantId();
        // 登录账号不能为空
        BooleanHandel.trueThrow(StringUtils.isBlank(sysUserForm.getUsername())).throwMessage(SystemErrorType.USER_NAME_EMPTY);
        // 手机号不能为空
        BooleanHandel.trueThrow(StringUtils.isBlank(sysUserForm.getMobile())).throwMessage(SystemErrorType.PHONE_EMPTY);
        // 部门不能为空
        BooleanHandel.trueThrow(sysUserForm.getDeptId() == null).throwMessage(SystemErrorType.DEPT_EMPTY);
        sysUserForm.setTenantId(tenantId);
        return this.saveUser(sysUserForm);
    }

    /**
     * 管理员修改用户
     *
     * @param sysUserForm
     * @return
     * @throws Exception
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public Boolean adminUpdateUser(SysUserForm sysUserForm) {
        BooleanHandel.trueThrow(Objects.isNull(sysUserForm.getId())).throwMessage(SystemErrorType.PRIMARY_KEY);
        SysUser sysUser = this.findByUserId(sysUserForm.getId());
        BooleanHandel.trueThrow(Objects.isNull(sysUser)).throwMessage(SystemErrorType.DATE_EMPTY);
        SysUser user = new SysUser();
        BeanUtils.copyProperties(sysUserForm, user);
        Boolean updateFlag = this.updateById(user);
        SpringContextHolder.publishEvent(new UserUpdateEvent(this, user));
        return updateFlag;
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    @Override
    public BaseUserVO userInfo() {
        BaseUserVO baseUserVO = new BaseUserVO();
        Boolean authStatus = UserContextHolder.getAuthStatus();
        List<Long> roleIds = UserContextHolder.getRoleIds();
        BooleanHandel.trueThrow(!authStatus).throwMessage(SystemErrorType.NO_LOGIN);
        String userName = UserContextHolder.getUsername();
        UserInfo userInfo = this.getUserInfo(userName);
        BeanUtils.copyProperties(userInfo, baseUserVO);
        baseUserVO.setPermissions(this.permissions(roleIds));
        return baseUserVO;
    }

    private List<BaseUserVO.Permission> permissions(List<Long> roleIds) {
        List<SysMenu> sysMenus = sysMenuService.userSysMenus(roleIds);
        return CollectionUtils.isNotEmpty(sysMenus) ? sysMenus.stream()
                .map(item -> {
                    BaseUserVO.Permission permission = new BaseUserVO.Permission();
                    permission.setLabel(item.getName());
                    permission.setValue(item.getAuth());
                    return permission;
                }).collect(Collectors.toList()) : Collections.emptyList();
    }

    private UserInfo getUserInfo(String userName) {
        Boolean hasKey = redisTemplateOps.hasKey(Constant.LOGIN_USER + userName);
        if (Boolean.TRUE.equals(hasKey)) {
            return (UserInfo) redisTemplateOps.get(Constant.LOGIN_USER + userName);
        }
        return new UserInfo();
    }

    /**
     * 搜索用户
     *
     * @param userPageParam
     * @return
     */
    @Override
    public List<UserPageVO> searchUser(UserPageParam userPageParam) {
        List<SysUser> sysUsers = this.list(new QueryWrapper<SysUser>().lambda()
                .like(StringUtils.isNotBlank(userPageParam.getName()), SysUser::getName, userPageParam.getName()));
        return CollectionUtils.isNotEmpty(sysUsers) ? sysUsers.stream().map(item -> {
            UserPageVO userPageVO = new UserPageVO();
            BeanUtils.copyProperties(item, userPageVO);
            return userPageVO;
        }).collect(Collectors.toList()) : Collections.emptyList();
    }

    /**
     * 更新用户租户
     *
     * @param updateUserTenantFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUserTenant(UpdateUserTenantFrom updateUserTenantFrom) {
        SysUser sysUser = new SysUser();
        sysUser.setId(updateUserTenantFrom.getUserId());
        sysUser.setTenantId(updateUserTenantFrom.getTenantId());
        return this.updateById(sysUser);
    }

    /**
     * 重置用户密码
     *
     * @param baseFrom
     * @return
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(BaseFrom baseFrom) throws Exception {
        Long tenantId = UserContextHolder.getTenantId();
        SysUser sysUser = this.findByUserId(baseFrom.getId());
        BooleanHandel.trueThrow(Objects.isNull(sysUser)).throwMessage(SystemErrorType.DATE_EMPTY);
        BooleanHandel.trueThrow(!sysUser.getTenantId().equals(tenantId)).throwMessage(SystemErrorType.NOT_BELONG_TENANT);
        TenantConfig tenantConfig = tenantConfigService.getTenantConfig(tenantId, TenantConfigEnum.DEFAULT_PASSWORD.code());
        String newPwd = AESUtil.aesDecrypt(tenantConfig.getConfigValue(), Constant.KEY);
        sysUser.setPassword(passwordEncoder().encode(newPwd));
        return this.updateById(sysUser);
    }

    /**
     * 用户修改密码
     *
     * @param updatePasswordFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(UpdatePasswordFrom updatePasswordFrom) throws Exception {
        Long userId = UserContextHolder.getUserId();
        SysUser sysUser = this.findByUserId(userId);
        BooleanHandel.trueThrow(Objects.isNull(sysUser)).throwMessage(SystemErrorType.DATE_EMPTY);
        String oldPassword = AESUtil.aesDecrypt(updatePasswordFrom.getOldPassword(), Constant.KEY);
        boolean matches = passwordEncoder().matches(oldPassword, sysUser.getPassword());
        BooleanHandel.trueThrow(!matches).throwMessage(SystemErrorType.OLD_PASSWORD_ERROR);
        BooleanHandel.trueThrow(!updatePasswordFrom.getNewPassword().equals(updatePasswordFrom.getConfirmPassword()))
                .throwMessage(SystemErrorType.NEW_PWD_CONFIRM_PWD);
        String password = AESUtil.aesDecrypt(updatePasswordFrom.getConfirmPassword(), Constant.KEY);
        sysUser.setPassword(passwordEncoder().encode(password));
        return this.updateById(sysUser);
    }

    /**
     * 用户更新基本信息
     *
     * @param updateUserForm
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSelf(UpdateUserForm updateUserForm) {
        Long userId = UserContextHolder.getUserId();
        this.checkMobileAndEmail(updateUserForm, userId);
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(updateUserForm, sysUser);
        sysUser.setId(userId);
        return this.updateById(sysUser);
    }

    /**
     * 验证手机号，邮箱不能重复
     *
     * @param updateUserForm
     */
    private void checkMobileAndEmail(UpdateUserForm updateUserForm, Long userId) {
        List<SysUser> mobileUsers = this.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getMobile, updateUserForm.getMobile()));
        mobileUsers.removeIf(item -> item.getId().equals(userId));
        BooleanHandel.trueThrow(CollectionUtils.isNotEmpty(mobileUsers)).throwMessage(SystemErrorType.MOBILE_REPEAT);
        List<SysUser> emailUsers = this.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getEmail, updateUserForm.getEmail()));
        emailUsers.removeIf(item -> item.getId().equals(userId));
        BooleanHandel.trueThrow(CollectionUtils.isNotEmpty(emailUsers)).throwMessage(SystemErrorType.EMAIL_REPEAT);
    }

    /**
     * 员工离职
     *
     * @param baseFrom
     * @return
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public boolean userDepart(BaseFrom baseFrom) {
        SysUser sysUser = this.userDataPermissions(baseFrom.getId());
        boolean updFlag = this.updateById(delTenantIdAndDeptId(sysUser));
        // 删除用户的所有角色
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, baseFrom.getId()));
        // 将用户的角色设置为普通用户角色
        sysUserRoleService.resetUserRole(baseFrom.getId());
        // 发布一个员工离职事件
        SpringContextHolder.publishEvent(new UserDepartEvent(this, baseFrom.getId()));
        return updFlag;
    }

    /**
     * 用户数据权限
     *
     * @param userId
     */
    @Override
    public SysUser userDataPermissions(Long userId) {
        Long tenantId = UserContextHolder.getTenantId();
        SysUser sysUser = this.findByUserId(userId);
        BooleanHandel.trueThrow(Objects.isNull(sysUser)).throwMessage(SystemErrorType.DATE_EMPTY);
        BooleanHandel.trueThrow(!sysUser.getTenantId().equals(tenantId)).throwMessage(SystemErrorType.NOT_BELONG_TENANT);
        return sysUser;
    }

    /**
     * 员工离职等其他操作设置租户ID和部门ID为空
     *
     * @param sysUser
     * @return
     */
    private SysUser delTenantIdAndDeptId(SysUser sysUser) {
        sysUser.setTenantId(Constant.NO_TENANT_AND_DEPT);
        sysUser.setDeptId(Constant.NO_TENANT_AND_DEPT);
        return sysUser;
    }

    /**
     * 根据用户IDS查询
     *
     * @param userListParam
     * @return
     */
    @Override
    public List<SysUser> userByIds(UserListParam userListParam) {
        List<SysUser> sysUsers = this.list(new QueryWrapper<SysUser>().lambda().in(SysUser::getId, userListParam.getUserIds()));
        return sysUsers.stream().peek(item -> item.setPassword("")).collect(Collectors.toList());
    }
}
